import * as utils from '../utils'
import { mat4, vec3 } from 'gl-matrix'

function createCourse28 (gl: WebGLRenderingContext, dom: HTMLCanvasElement) {
  gl.enable(gl.DEPTH_TEST)
  gl.clearColor(0.0, 0.0, 0.0, 1.0)
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

  const vectexShaderSrc = `
  uniform mat4 u_mvpMatrix;
  uniform vec3 u_LightDirection;
  uniform vec3 u_LightColor;
  uniform vec3 u_AmbientLight;
  attribute vec4 a_Position;
  attribute vec4 a_Color;
  attribute vec4 a_Normal;
  varying vec4 v_Color;
    void main () {
        gl_Position = u_mvpMatrix * a_Position;
        vec3 ambient = u_AmbientLight * a_Color.rgb;
        vec3 normal = normalize(a_Normal.xyz);
        float nDotL = max(dot(u_LightDirection, normal), 0.0);
        vec3 diffuse = u_LightColor * a_Color.rgb * nDotL;
        v_Color = vec4(diffuse + ambient, a_Color.a);
    }
  `

  const fragmentShaderSrc = `
    precision mediump float;
    varying vec4 v_Color;
        void main () {
            gl_FragColor = v_Color;
        }
  `

  const program = utils.initShaders(gl, vectexShaderSrc, fragmentShaderSrc)

  const vertics = new Float32Array([
    -0.2, -0.2, +0.2, +0.2, -0.2, +0.2, +0.2, +0.2, +0.2, -0.2, +0.2, +0.2,
    +0.2, -0.2, -0.2, -0.2, -0.2, -0.2, -0.2, +0.2, -0.2, +0.2, +0.2, -0.2,

    -0.2, -0.2, -0.2, -0.2, -0.2, +0.2, -0.2, +0.2, +0.2, -0.2, +0.2, -0.2,
    +0.2, -0.2, +0.2, +0.2, -0.2, -0.2, +0.2, +0.2, -0.2, +0.2, +0.2, +0.2,

    -0.2, +0.2, +0.2, +0.2, +0.2, +0.2, +0.2, +0.2, -0.2, -0.2, +0.2, -0.2,
    -0.2, -0.2, -0.2, +0.2, -0.2, -0.2, +0.2, -0.2, +0.2, -0.2, -0.2, +0.2
  ])

  const colors = new Float32Array([
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0
  ])

  const normals = new Float32Array([
    0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
    0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0,
    -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
    1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
    0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0
  ])

  const indeics = new Uint8Array([
    0, 1, 2, 0, 2, 3,
    4, 5, 6, 4, 6, 7,

    8, 9, 10, 8, 10, 11,
    12, 13, 14, 12, 14, 15,

    16, 17, 18, 16, 18, 19,
    20, 21, 22, 20, 22, 23
  ])
  const size = vertics.BYTES_PER_ELEMENT
  const vertexBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, vertics, gl.STATIC_DRAW)

  const aPosition = gl.getAttribLocation(program, 'a_Position')
  gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, size * 3, 0)
  gl.enableVertexAttribArray(aPosition)

  const colorBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW)
  const aColor = gl.getAttribLocation(program, 'a_Color')
  gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, size * 3, 0)
  gl.enableVertexAttribArray(aColor)

  const normalBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, normals, gl.STATIC_DRAW)
  const aNormal = gl.getAttribLocation(program, 'a_Normal')
  gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, size * 3, 0)
  gl.enableVertexAttribArray(aNormal)

  const indeicsBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indeicsBuffer)
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indeics, gl.STATIC_DRAW)

  const projMatrix = mat4.create()
  mat4.perspective(projMatrix, 70, dom.offsetWidth / dom.offsetHeight, 0.01, 5)

  const viewMatrix = mat4.create()
  const eye = vec3.create()
  vec3.set(eye, 0.5, 0.5, 1)
  const center = vec3.create()
  vec3.set(center, 0.0, 0.0, 0.0)
  const up = vec3.create()
  vec3.set(up, 0.0, 1.0, 0.0)
  mat4.lookAt(viewMatrix, eye, center, up)

  const modelMatrix = mat4.create()
  const x = vec3.create()
  vec3.set(x, 0.1, 0.0, 0.0)
  mat4.fromTranslation(modelMatrix, x)

  const viewModelMatrix = mat4.create()
  mat4.multiply(viewModelMatrix, viewMatrix, modelMatrix)

  const mvpMatrix = mat4.create()
  mat4.multiply(mvpMatrix, projMatrix, viewModelMatrix)

  const uMvpMatrix = gl.getUniformLocation(program, 'u_mvpMatrix')
  gl.uniformMatrix4fv(uMvpMatrix, false, mvpMatrix)

  const lightDirection = vec3.create()
  vec3.set(lightDirection, 1, 3.0, 4.0)
  // 必须归一化
  vec3.normalize(lightDirection, lightDirection)
  const uLightDirection = gl.getUniformLocation(program, 'u_LightDirection')
  gl.uniform3fv(uLightDirection, lightDirection)

  const uLightColor = gl.getUniformLocation(program, 'u_LightColor')
  gl.uniform3f(uLightColor, 1.0, 1.0, 1.0)

  const uAmbientLight = gl.getUniformLocation(program, 'u_AmbientLight')
  gl.uniform3f(uAmbientLight, 0.2, 0.2, 0.2)

  gl.drawElements(gl.TRIANGLES, indeics.length, gl.UNSIGNED_BYTE, 0)
}

export {
  createCourse28
}
